<template>
  <div class="c-table">
    <!-- 表头操作栏 -->
    <CtableTitle @addClick="addClick" :crudModalVisible="crudModalVisible" @updateColumns="updateColumns" @selectRemoveBtn="handleSelectRemove" @update:agencyColumns="handleUpdateAgencyColumns" :options="options" ref="title" :columns="computedColumns">
      <!-- 标题插槽 -->
      <template v-slot:title> <slot name="title"></slot></template>
      <!-- 头部操作栏插槽 -->
      <template v-slot:header> <slot name="header"></slot></template>
    </CtableTitle>
    <a-table
      :row-selection="props.options.rowSelection ? rowSelection : null"
      :rowClassName="(record: any, index: number) => (seting.tableStripedChecked ? index % 2 === 1 ? 'table-striped' : null : null)"
      :size="seting.tableSize"
      :dataSource="newDataSource"
      :columns="computedColumns"
      :bordered="options.border ? options.border : false"
      :scroll="props.scroll ? props.scroll : { x: true, y: true }"
      :loading="options.loading ? options.loading : false"
      :defaultExpandAllRows="options.defaultExpandAllRows ? options.defaultExpandAllRows : true"
      :defaultExpandedRowKeys="options.defaultExpandedRowKeys ? options.defaultExpandedRowKeys : []"
    >
      <template v-for="(item, n) in computedColumns" :key="n" v-slot:[item.key]="{ text, record, index }">
        <template v-if="item.edit">
          <div class="editable-cell">
            <!-- 当前单元格编辑状态为真，显示编辑框 -->
            <div v-if="editing[record.editKey] === item.key" class="editable-cell-input-wrapper">
              <a-input v-model:value="editableData[record.editKey][item.key]" @pressEnter="save(record, item)" />
              <CheckOutlined class="editable-cell-icon-check" @click="save(record, item)" />
            </div>
            <!-- 当前单元格编辑状态为假，显示文本 -->
            <div style="cursor: pointer" v-else class="editable-cell-text-wrapper" @click="edit(record, item)">
              {{ text || ' ' }}
              <EditOutlined class="editable-cell-icon" />
            </div>
          </div>
        </template>

        <template v-if="!item.edit">
          <!-- 自定义渲染 -->
          <div :class="item.click ? 'cell-click cell' : 'cell'" v-if="item.render" @click="item.click ? item.click(text, record) : null" v-html="item.render(text)"></div>
          <!-- button 操作按钮  -->
          <div class="ctable-group" v-else-if="item.group">
            <template v-for="(items, idx) in item.group" :key="items.key">
              <a-popconfirm placement="left" v-if="items.popconfirm" :title="`是否确定${items.text}`" ok-text="确定" cancel-text="取消" @confirm="items.click ? items.click(record, index) : null">
                <span class="ctable-group-button" :type="items.type">{{ items.text }}</span>
              </a-popconfirm>
              <!--  当存在编辑配置的时候 需要给操作栏添加上编辑按钮 -->
              <span v-if="crudEditConfig.length > 0 && idx === 0" @click="onRowEdit(record, index)" class="ctable-group-button">编辑</span>
              <span v-else-if="idx > 0 && idx === 0" @click="items.click ? items.click(record, index) : null" class="ctable-group-button" :type="items.type">{{ items.text }}</span>
            </template>
          </div>

          <!-- 单元格不可编辑，直接显示文本 -->
          <div v-else :class="item.click ? 'cell-click cell' : 'cell'" @click="item.click ? item.click(text, record) : null">{{ text || ' ' }}</div>
        </template>
      </template>
      <!-- 页脚插槽 -->
      <template #footer><slot name="footer"></slot></template>
    </a-table>
  </div>
  <CtableCrud :crudAddConfig="crudAddConfig" :crudEditConfig="crudEditConfig" :formData="formData" :config="props.crudConfig" :crudModalVisible="crudModalVisible" @handleOk="crudModaHandleOk" @handleCancel="crudModaHandleCancel"></CtableCrud>
</template>

<script lang="ts" setup name="Ctable">
import { Modal } from 'ant-design-vue'
import { createVNode } from 'vue'
import CtableTitle from './title.vue'
import CtableCrud from './crud.vue'
import { CheckOutlined, EditOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue'
import { TableRecordType, TableColumnType, RowSelectionType, TableCrudItemType } from './types'

const props = defineProps({
  dataSource: {
    type: Array as () => TableRecordType[],
    required: true
  },
  options: {
    type: Object,
    default: () => ({}),
    required: true
  },
  columns: {
    type: Array as () => TableColumnType[],
    required: true
  },
  scroll: {
    type: Object as () => TableRecordType[]
  },
  crudConfig: {
    type: Object,
    required: false
  },
  crudAddConfig: {
    type: Object,
    required: false
  },
  crudEditConfig: {
    type: Object,
    required: false
  }
})

// 当存在编辑配置的时候 需要给操作栏添加上编辑按钮
const crudEditConfig = ref(props.crudEditConfig || [])

const formData = ref()

const onRowEdit = (record: TableRecordType) => {
  formData.value = record
  crudModalVisible.value = true
}

const crudAddConfig = ref(props.crudAddConfig || [])

// 当配置了添加按钮但是没有配置添加项是 会自动给其加上添加配置
if (!props.crudAddConfig && props.options.addBtn) {
  const cstCrudAddConfig = props.columns.map(({ key, title }) => ({
    type: 'a-input',
    key,
    label: title
  }))
  crudAddConfig.value = cstCrudAddConfig
}

// 获取子组件实例
const title = ref()
const seting = ref({ tableStripedChecked: false, tableSize: 'middle' })
onMounted(() => {
  seting.value = title.value ? title.value.seting : null
})

// 更新表头数据
const handleUpdateAgencyColumns = (agencyColumns: any) => {
  columns.value = agencyColumns
}

// 表头配置
const columns = ref(props.columns)
// 配置项
const options = ref(props.options)
// 选择功能
const rowSelection = ref<RowSelectionType>({})

// 组件选择框Change事件
const emits = defineEmits(['selectChange', 'selectAll', 'select', 'selectRemove', 'cellEdit', 'rowEdit'])

// 编辑模态框开关
const crudModalVisible = ref(false)

// 添加按钮打开模态框
const addClick = (value: boolean) => {
  crudModalVisible.value = value
}

// 模态框确定事件
const crudModaHandleOk = (value: boolean, record: TableRecordType) => {
  crudModalVisible.value = value
  console.log(record)
}

// 模态框取消事件
const crudModaHandleCancel = (value: boolean) => {
  crudModalVisible.value = value
}

// 删除按事件
const handleSelectRemove = (selectList: Array<any>) => {
  emits('selectRemove', selectList)
}

// 组件选择框事件
const onSelectChange = (selectedRowKeys: Array<any>, selectedRows: Array<any>) => {
  emits('selectChange', selectedRowKeys, selectedRows)
}

// 组件选择框全选事件
const onSelectAll = (selected: boolean, selectedRows: Array<any>, changeRows: Array<any>) => {
  emits('selectAll', selected, selectedRows, changeRows)
  title.value.setSelectList(selectedRows)
}

// 组件选择框单选选事件
const onSelect = (record: TableRecordType, selected: boolean, selectedRows: Array<any>) => {
  emits('select', record, selected, selectedRows)
  title.value.setSelectList(selectedRows)
}

if (options.value && options.value.rowSelection) {
  rowSelection.value.onChange = onSelectChange
  rowSelection.value.onSelect = onSelect
  rowSelection.value.onSelectAll = onSelectAll
}

const isInit = ref(true)

const computedColumns = computed(() => {
  const newColumns = [...columns.value]

  // 动态添加 slots 和 dataIndex 属性
  newColumns.forEach((column: TableRecordType) => {
    column.dataIndex = column.key
    column.isShowColumn = true
    if (!column.slots || !column.render) {
      column.slots = { customRender: column.key }
    }
  })

  if (isInit.value && options.value.index && newColumns.findIndex((item) => item.key == 'index') == -1) {
    newColumns.unshift(
      reactive({
        title: '序号',
        key: 'index',
        dataIndex: 'index',
        width: 70, // 设置列宽
        align: 'center',
        slots: { customRender: 'index' }
      })
    )
    props.dataSource.forEach((record: TableRecordType, index: number) => {
      record.index = index += 1
    })
  }
  isInit.value = false
  return newColumns
})

const updateColumns = (list: any) => {
  if (list) {
    columns.value = list
    if (props.dataSource && list.findIndex((item: any) => item.key == 'index') != -1) {
      props.dataSource.forEach((record: TableRecordType, index: number) => {
        record.index = index += 1
      })
    }
  }
}

// 存储每个单元格的编辑状态
const editing: TableRecordType = ref({})

// 存储每个单元格的编辑数据
const editableData: TableRecordType = ref({})

const newDataSource = computed(() => {
  const newData = [...props.dataSource]
  newData.forEach((record: TableRecordType, index: number) => {
    // 操蛋的操作 a-table 组件非要data有一个唯一的key 为了兼容请求来的数据 这里做了处理
    if (!record.key) {
      record.key = index
    }
    record.editKey = index
    // 默认情况下，所有单元格都不处于编辑状态
    editing.value[record.editKey] = false
    // 初始化编辑数据为空对象
    editableData.value[record.editKey] = {}
  })
  return newData
})

const edit = (record: TableRecordType, item: TableRecordType) => {
  // 标记当前单元格为编辑状态
  editing.value[record.editKey] = item.key
  // 将当前单元格的值存储到 editableData 中
  editableData.value[record.editKey][item.key] = record[item.key]
}

const save = (record: TableRecordType, item: TableRecordType) => {
  const newValue = editableData.value[record.editKey][item.key]
  // 如果当前单元格的值发生变化，更新 record 中的值
  if (record[item.key] == newValue) {
    editing.value[record.editKey] = false
    return
  }

  Modal.confirm({
    title: '是否确认修改',
    icon: createVNode(ExclamationCircleOutlined),
    okText: '确认',
    cancelText: '取消',
    onOk() {
      // 如果当前单元格的值发生变化，更新 record 中的值
      if (record[item.key] !== newValue) {
        record[item.key] = newValue
      }
      // 将当前单元格的编辑状态和数据清除
      delete editableData.value[record.editKey][item.key]
      editing.value[record.editKey] = false
      emits('cellEdit', record)
    },
    onCancel() {
      editing.value[record.editKey] = false
    }
  })
}
</script>

<style lang="less">
@import './index.less';
</style>
